/************************************************************************/
// Copyright (C) 2016, han_gangbiao. All rights reserved.
// Use of this source code is governed by a GPL-v2 license that can be found in the License file.
// 
// [Time]:      2016-1-4 21:53:17
// [Author]:    han_gangbiao [http://my.oschina.net/jackhen]
// [Info]:      
/************************************************************************/

#ifndef INCLUDE_BASE_XEVENT_H_
#define INCLUDE_BASE_XEVENT_H_

#include "baseheader.h"
#include "xmutex.h"

BEG_NS_SMART

#   define X_EVENT_Signal(evt)          pthread_cond_t evt
#   define X_EVENT_SigConstruct(evt)    pthread_cond_init(&evt, NULL)
#   define X_EVENT_SigDestruct(evt)     pthread_cond_destroy(&evt)
#   define X_EVENT_SigSet(evt)          pthread_cond_signal(&evt)
#   define X_EVENT_SigReset(evt)        do { } while(0)
#   define X_EVENT_SigWait(evt, lck, timeout_ms, result) \
    do { \
        int tmp = 0; \
        if(timeout_ms == -1) { \
            tmp = pthread_cond_wait(&evt, &lck.m_mtx); \
        } \
        else { \
            struct timespec t; \
            clock_gettime(CLOCK_REALTIME, &t); \
            t.tv_sec += timeout_ms / 1000; \
            t.tv_nsec += (timeout_ms % 1000) * 1000 * 1000; \
            if(t.tv_nsec >= 1000 * 1000 * 1000) { \
                t.tv_sec += 1; \
                t.tv_nsec -= 1000 * 1000 * 1000; \
            } \
            tmp = pthread_cond_timedwait(&evt, &lck.m_mtx, &t); \
        } \
        result = (tmp == 0) ? 0 : -1; \
    } while(0)


class event_t
{
public:
    event_t();
    ~event_t();
    
    inline int setEvent() { lock(); int ret = setEventInLock(); unlock(); return ret; }
    int reset();

    inline int wait() { return timedWait(-1); }
    inline int timedWait(int timeout_ms) { lock(); int ret = timedWaitInLock(timeout_ms); unlock(); return ret; }

    inline void lock() { m_mutex.lock(); }
    inline void unlock() { m_mutex.unlock(); }

    int setEventInLock();

    int timedWaitInLock(int timeout_ms);
    
private:
    mutex_t m_mutex;
    bool m_bSet;
    X_EVENT_Signal(m_evt);
};


END_NS_SMART

#endif //~INCLUDE_BASE_XEVENT_H_
